import json
import sys
import time

from PySide6.QtWidgets import QWidget, QGridLayout, QLabel, QTextEdit, QComboBox, QPushButton, QApplication
from easy_tools.utils.json_to import parse_json_metadata, to_hump, to_char_sep_lower


class JsonToCodeWidget(QWidget):

    def __init__(self):
        super().__init__()
        self._init()

    def _init(self):
        self._type_to_java = {
            str: {
                'import': '',
                'class': 'String'
            },
            int: {
                'import': '',
                'class': 'Long',
            },
            float: {
                'import': 'java.math.BigDecimal',
                'class': 'BigDecimal'
            },
            bool: {
                'import': '',
                'class': 'Boolean'
            },
            object: {
                'import': '',
                'class': 'Object'
            },
            list: {
                'import': 'java.util.List',
                'class': 'List',
            },
            tuple: {
                'import': 'java.util.List',
                'class': 'List',
            }
        }
        self.support_language = ['java-lombok']
        self.column_types = ['驼峰', '下划线小写', '中划线小写']
        grid = QGridLayout()
        self.setLayout(grid)
        self.input_widget = QTextEdit('', self)
        self.json_check_widget = QLabel('不是有效的JSON')
        self.json_check_widget.setStyleSheet("color: red")
        self.json_check_widget.hide()
        self.choice = QComboBox(self)
        self.choice.addItems(self.support_language)
        self.column_type_widget = QComboBox(self)
        self.column_type_widget.addItems(self.column_types)
        self.confirm = QPushButton('生成', self)
        self.output_widget = QTextEdit('', self)

        x = 0
        grid.addWidget(QLabel('JSON: ', self), x, 0)
        grid.addWidget(self.input_widget, x, 1)
        grid.addWidget(QLabel('输出: '), x, 2)
        grid.addWidget(self.output_widget, x, 3)
        x += 1
        grid.addWidget(self.json_check_widget, x, 1)
        x += 1
        grid.addWidget(QLabel('生成语言: ', self), x, 0)
        grid.addWidget(self.choice, x, 1)
        grid.addWidget(QLabel('字段规则: ', self), x, 2)
        grid.addWidget(self.column_type_widget, x, 3)
        x += 1
        grid.addWidget(self.confirm, x, 0, 1, 4)

        self.input_widget.textChanged.connect(self._json_check)
        self.confirm.clicked.connect(self._generate)

    def _json_check(self):
        text = self.input_widget.toPlainText()
        try:
            json.loads(text)
            self.json_check_widget.hide()
        except json.decoder.JSONDecodeError:
            self.json_check_widget.show()

    def _generate(self):
        infos = self._parse_json_data()
        if self.choice.currentText() == 'java-lombok':
            self._generate_java_lombok(infos)

    def _parse_json_data(self):
        data = json.loads(self.input_widget.toPlainText())
        return parse_json_metadata('JavaRootBean', data)

    def _generate_java_lombok(self, infos):
        code = '''package com.xianyu.tools;\n\nimport lombok.Data;\n'''
        type_set = set()

        class_code = ''
        for info in infos:
            class_code += f"""\n/**
 * XianYu auto-generated
 *
 * @author dragons
 * @since {time.strftime("%Y/%m/%d %H:%M")}
 */\n"""
            class_code += '@Data\n'
            class_code += 'class ' + to_hump(info['class']) + ' {\n\n'
            for field in info['fields']:
                field_name = self._get_field_name(field["field"])
                class_code += f"""    /**
     * {field_name}
     */\n"""
                if field['type'] in (dict, ):
                    class_code += f'    private {to_hump(field["field"])} {field_name};\n\n'
                elif field['type'] in (tuple, list):
                    off = 0
                    class_code += f'    private {self._type_to_java[field["type"]]["class"]}'
                    for generic in field['generics']:
                        off += 1
                        if generic in (dict, ):
                            class_code += '<' + to_hump(field['field'])
                        else:
                            class_code += '<' + self._type_to_java[generic]['class']
                    for i in range(off):
                        class_code += '>'
                    class_code += f" {field_name};\n\n"
                else:
                    class_code += f'    private {self._type_to_java[field["type"]]["class"]} {field_name};\n\n'
                type_set.add(field['type'])
                for generic in field['generics']:
                    type_set.add(generic)
            class_code += "}\n"

        if dict in type_set:
            type_set.remove(dict)

        for tp in type_set:
            if self._type_to_java[tp]['import']:
                code += 'import ' + self._type_to_java[tp]['import'] + ';\n'

        code += class_code
        self.output_widget.setText(code)

    def _get_field_name(self, name):
        column_type = self.column_type_widget.currentText()
        if column_type == '驼峰':
            return to_hump(name, False)
        elif column_type == '下划线小写':
            return to_char_sep_lower(name, '_')
        elif column_type == '中划线小写':
            return to_char_sep_lower(name, '-')
        return name


if __name__ == '__main__':
    app = QApplication()
    win = JsonToCodeWidget()
    win.show()
    sys.exit(app.exec())
